﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;

#if !NETCOREAPP3_0_OR_GREATER
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
#endif

namespace XQ.Framework.WeChatPay
{
    public class WeChatPayV3Signature
    {
        /// <summary>
        /// 生成微信支付V3签名
        /// </summary>
        public static string GenerateSignature(string signString, string privateKey)
        {
            //// 1. 构造签名串
            //string signString = BuildSignString(method, url, timestamp, nonce, body);

            // 2. 使用私钥签名
            byte[] signatureBytes = SignWithPrivateKey(signString, privateKey);

            // 3. Base64编码
            return Convert.ToBase64String(signatureBytes);
        }

        /// <summary>
        /// 构造V3签名串
        /// </summary>
        private static string BuildSignString(string method, string url, string timestamp,
            string nonce, string body)
        {
            // 格式化URL
            string formattedUrl = FormatUrl(url);

            // 标准化请求体
            string bodyContent = string.IsNullOrEmpty(body) ? "" : body.Trim();

            // 微信支付V3签名串格式
            return $"{method}\n{formattedUrl}\n{timestamp}\n{nonce}\n{bodyContent}\n";
        }

        /// <summary>
        /// 格式化URL
        /// </summary>
        private static string FormatUrl(string url)
        {
            // 处理相对URL
            if (!url.StartsWith("http"))
            {
                // 移除查询参数
                int queryIndex = url.IndexOf('?');
                return queryIndex >= 0 ? url.Substring(0, queryIndex) : url;
            }

            // 处理绝对URL
            var uri = new Uri(url);
            return uri.AbsolutePath;
        }

        /// <summary>
        /// 从PKCS#8格式的PEM私钥创建RSA实例
        /// </summary>
        public static byte[] SignWithPrivateKey(string data, string pemPrivateKey)
        {
            // 3. 创建RSA实例并导入私钥
            using (var rsa = CreateRsaFromPkcs8PrivateKey(pemPrivateKey))
            {
                // 4. 计算SHA256哈希
                byte[] dataBytes = Encoding.UTF8.GetBytes(data);
                byte[] hash;
                using (SHA256 sha256 = SHA256.Create())
                {
                    hash = sha256.ComputeHash(dataBytes);
                }

                // 5. 使用私钥创建签名（加密哈希）
                byte[] signature = rsa.SignHash(
                    hash,
                    CryptoConfig.MapNameToOID("SHA256")
                );

                //Console.WriteLine("数字签名: " + Convert.ToBase64String(signature));

                //// 7. 验证签名（可选，用于自我检查）
                //bool isValid = rsa.VerifyHash(
                //    hash,
                //    CryptoConfig.MapNameToOID("SHA256"),
                //    signature
                //);
                //Console.WriteLine("签名验证: " + (isValid ? "成功" : "失败"));

                return signature;
            }

        
        }

        ///// <summary>
        ///// 从PKCS#8格式的PEM私钥创建RSA实例
        ///// </summary>
        //private static RSACryptoServiceProvider CreateRsaFromPkcs8PrivateKey(string pemPrivateKey)
        //{
        //    // 去除PEM格式的页眉页脚
        //    string base64 = pemPrivateKey
        //        .Replace("-----BEGIN PRIVATE KEY-----", "")
        //        .Replace("-----END PRIVATE KEY-----", "")
        //        .Replace("\n", "")
        //        .Replace("\r", "")
        //        .Trim();

        //    // 解析私钥
        //    byte[] privateKeyBytes = Convert.FromBase64String(base64);

        //    // 使用X509Certificate2解析PKCS#8
        //    var cert = new X509Certificate2(
        //        privateKeyBytes,
        //        (string)null,
        //        X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet
        //    );

        //    // 获取RSA私钥
        //    var rsaPrivateKey = cert.GetRSAPrivateKey() as RSACryptoServiceProvider;

        //    if (rsaPrivateKey == null)
        //    {
        //        throw new InvalidOperationException("无法从私钥创建RSA实例");
        //    }

        //    return rsaPrivateKey;
        //}

        /// <summary>
        /// 使用BouncyCastle库解析PKCS#8格式的PEM私钥
        /// </summary>
        private static RSACryptoServiceProvider CreateRsaFromPkcs8PrivateKey(string pemPrivateKey)
        {
            using (var reader = new System.IO.StringReader(pemPrivateKey))
            {
                // 创建PEM解析器
                var pemReader = new PemReader(reader);

                // 直接读取私钥参数（而不是密钥对）
                var privateKeyParams = pemReader.ReadObject() as RsaPrivateCrtKeyParameters;

                if (privateKeyParams == null)
                {
                    throw new InvalidOperationException("无法解析PKCS#8私钥");
                }

                // 转换为.NET的RSAParameters
                var rsaParams = DotNetUtilities.ToRSAParameters(privateKeyParams);

                // 创建并配置RSACryptoServiceProvider
                var rsa = new RSACryptoServiceProvider();
                rsa.ImportParameters(rsaParams);

                return rsa;
            }
        }

        /// <summary>
        /// 解析PEM格式的私钥
        /// </summary>
        private static AsymmetricKeyParameter ParsePrivateKey(string privateKey)
        {
            // 重新添加PEM标记
            string pem = "-----BEGIN PRIVATE KEY-----\n" +
                        privateKey +
                        "\n-----END PRIVATE KEY-----";

            using (var reader = new StringReader(pem))
            {
                var pemReader = new PemReader(reader);
                var keyPair = pemReader.ReadObject() as AsymmetricCipherKeyPair;
                return keyPair.Private;
            }
        }


        /// <summary>
        /// 清理PEM格式的密钥
        /// </summary>
        private static string CleanPemKey(string pemKey)
        {
            return Regex.Replace(pemKey,
                @"-----BEGIN (RSA )?PRIVATE KEY-----|-----END (RSA )?PRIVATE KEY-----|\s+",
                "");
        }

        /// <summary>
        /// 生成Authorization头
        /// </summary>
        public static string GenerateAuthorizationHeader(
            string mchId, string serialNo, string signature,
            string timestamp, string nonce)
        {
            return $"WECHATPAY2-SHA256-RSA2048 " +
                   $"mchid=\"{mchId}\"," +
                   $"nonce_str=\"{nonce}\"," +
                   $"signature=\"{signature}\"," +
                   $"timestamp=\"{timestamp}\"," +
                   $"serial_no=\"{serialNo}\"";
        }

        /// <summary>
        /// 生成随机字符串
        /// </summary>
        public static string GenerateNonce(int length = 32)
        {
            const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            var random = new Random();
            var nonce = new char[length];
            for (int i = 0; i < length; i++)
            {
                nonce[i] = chars[random.Next(chars.Length)];
            }
            return new string(nonce);
        }

        /// <summary>
        /// 生成时间戳（秒级）
        /// </summary>
        public static string GenerateTimestamp()
        {
            return DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
        }

    }
}